#ifndef CMD_MANAGER_H
#define CMD_MANAGER_H

#include "cmd_view.h"
#include "cmd_sock_reader.h"
#include "multi_commander.h"

#include <string>
#include <map>
#include <boost/bind.hpp>

namespace vpm
{
	namespace cmo 
	{
		static const std::string cmd_help = "help";
		static const std::string cmd_ls   = "ls";
		static const std::string cmd_cd_view = "cd (view)";
		static const std::string cmd_about   = "about";
		static const std::string cmd_exit   = "exit";

		class CmdManager : public MultiCommander 
		{	
			typedef std::map<std::string , CmdViewPtr> CmdViewMap;
		public:

			CmdManager()
			{		
				m_cmdReader.reset(new  CmdSockReader(&m_defaultView));
				m_cmdReader->user_login();

				CmdViewAccess::attach_string_writer(m_defaultView,boost::bind(&CmdSockReader::write_string,(CmdSockReader*)m_cmdReader.get(),_1));
				CmdViewAccess::attach_char_writer(m_defaultView,boost::bind(&CmdSockReader::write_char,(CmdSockReader*)m_cmdReader.get(),_1));

				m_viewMap.insert(std::make_pair(m_defaultView.view_name(),&m_defaultView));
				m_defaultView.add_command(cmd_help,this);		
				m_defaultView.add_command(cmd_ls,this);
				m_defaultView.add_command(cmd_cd_view,this);
				m_defaultView.add_command(cmd_about,this);
				m_defaultView.add_command(cmd_exit,this);
			}
			void start()
			{
				m_cmdReader->parse();
			}

			void add_view(const std::string & view, const std::string & prompt= ">")
			{
				CmdView * pCmdView = new CmdView(); 

				CmdViewAccess::attach_char_writer(*pCmdView,boost::bind(&CmdSockReader::write_char,(CmdSockReader*)m_cmdReader.get(),_1));
				CmdViewAccess::attach_string_writer(*pCmdView,boost::bind(&CmdSockReader::write_string,(CmdSockReader*)m_cmdReader.get(),_1));
				pCmdView->view_prompt(prompt);
				m_viewMap.insert(std::make_pair(view,pCmdView));
			}

			void add_command(const std::string & view, Commander * pCmd)
			{
				CmdView * pCmdView = this->get_view(view); 
				if (pCmdView != NULL)
				{		
					pCmdView->add_command(pCmd->command(),pCmd);
				}
			}

			void add_command(const std::string & view, const std::string & cmd, Commander * pCmd)
			{
				CmdView * pCmdView = this->get_view(view); 
				if (pCmdView != NULL)
				{		
					pCmdView->add_command(cmd,pCmd);
				}
			}

			CmdView * get_view(const std::string & view)
			{
				CmdViewMap::iterator itr = m_viewMap.find(view);
				if (itr != m_viewMap.end())
				{
					return itr->second ;
				}
				return &m_defaultView; 
			}

			void change_view(const std::string& view)
			{
				CmdView * pView = this->get_view(view);
				m_cmdReader->change_view(pView);
			}

			void nonspace_action(char ch)
			{ 

			}

			void space_action()
			{

			}

			void control_action()
			{

			}

			virtual void operator()(const std::string & cmd)
			{
				std::cout <<std::endl<<"input command :"<< cmd <<std::endl; 
				if (cmd == cmd_help)
				{

				}else if (cmd == cmd_about)
				{
					std::cout <<"Auto Command Platform v1.0"<<std::endl;
				}else if (cmd == cmd_cd_view)
				{
					std::string  view = this->get_cmdword(cmd,1);		
					this->change_view(view);
				}
				else if (cmd == cmd_exit)
				{
					m_cmdReader->user_logout();
				}
			}

		private:
			CmdViewMap m_viewMap; 
			CmdView m_defaultView; 
			std::auto_ptr<CmdReader > m_cmdReader; 
		};
	}
}

#endif // 
